#!/usr/bin/groovy

// load pipeline functions
@Library('pipeline@master')
// import json parser
import groovy.json.JsonSlurper

def name = 'symphony'

// usually do not need to change the following variables
def project_repo_url = "https://github.com/umarkcloud/${name}.git"
def credentialsId = 'umarkgithubaccess'
def registry='registry.umarkcloud.com:8090'
def node_label = "cd4${name}"
def build_node_label = 'docker-build'

def is_prod = true
def is_release =false
def isManual = true
def cloud = is_prod ? "csxtest": "kubernetes"
def https_proxy = is_prod ? "http://10.16.70.198:3128": ""

podTemplate(label: node_label, containers: [
        containerTemplate(
                name: 'jnlp',
                image: 'registry.umarkcloud.com:8088/jenkins-slave-docker:1.1',
                args: '${computer.jnlpmac} ${computer.name}'),
        containerTemplate(name: 'helm', image: 'lachlanevenson/k8s-helm:v2.6.0', command: 'cat', ttyEnabled: true)],
        imagePullSecrets: [ 'umarkregsecret' ],
        serviceAccount:'jenkins',
        envVars: [
            envVar(key: 'HTTPS_PROXY', value: https_proxy),
        ],
        cloud: cloud
) {
    try {
        def ppl = new com.umarkcloud.ci.Pipeline()
        def ns = is_prod ? 'paas': 'paas-staging'
        def deploy_name = is_prod ? 'symphony': 'symphony-staging'
        def deploy_name_ops = is_prod ? 'fabric': 'fabric-staging'
        def set_options_fabric = [:]
        def set_options_symphony = [:]
        def fabric_prod_options = [
            'persistence.fabricGlusterVolumeName':'fabric-prod',
            'persistence.fabricMspPvName':'fabric-msp-prod-pv',
            'orderer.persistence.ordererDataVolume':'orderer-prod',
            'orderer.persistence.ordererDataPv':'orderer-data-pv',
            'orderer.autoCleanup': 'false']
        def symphony_prod_options = [
            'oboe-rest.ingress.hosts[0]':'oboe.umarkcloud.com',
            'oboe-rest.mongodb.database':'oboe-rest-prod']
        def build_changes = [:]
        node("${build_node_label}") {
            stage("Check out ${name} latest code") {
                // NOTE: as we need to retrieve previous version for package.json,
                // we have to turn off *shallow* option
                checkout changelog: false, poll: false,
                        scm: [$class: 'GitSCM', branches:  [[name:'*/prod']],
                              userRemoteConfigs: [[credentialsId: credentialsId, url: project_repo_url]]]
            }
            // set additional git envvars for image tagging
            ppl.gitEnvVars()
            // only build image when "Circle CI" user does version bump
            if (env.GIT_SHA != ppl.gitLastBy("Circle") && !is_prod && !is_release && !isManual) {
                currentBuild.result="NOT_BUILT"
                println "skip build image as last build is not commited by Circle CI"
                return
            }
            // parse package.json to know various version info
            def confName = is_release ? 'package-release.json': 'package.json'
            def packages = ppl.parseJsonFile(confName)
            def build_args = []
            def args_map = [
                "@umark/cornet-common": "CORNET_VERSION",
                "@umark/oboe": "OBOE_VERSION",
                "@umark/oboe-common": "OBOE_COMPOSER_VERSION",
                "@umark/orgel": "ORGEL_VERSION"]
            packages.dependencies.each { k, v -> if (k in args_map) build_args << "${args_map[k]}=$v" }
            build_option = build_args? "--build-arg ${build_args.join(' --build-arg ')}" : ''
            println "build args that will passed to docker build:\n$build_option"
            // def versionTag = packages.version
            def versionTag = "${packages.version}-prod"

            // get previous version of package.json
            def prevPackages = ppl.parseJsonText(ppl.gitLastVersionBy(confName, "Circle"))

            def deps = packages.dependencies
            def prevDeps = prevPackages.dependencies
            println "current dependencies:\n${deps}"
            println "previous dependencies:\n${prevDeps}"
            def cornetChanged = prevDeps["@umark/cornet-common"] != deps["@umark/cornet-common"]
            def oboeChanged = prevDeps["@umark/oboe"] != deps["@umark/oboe"]
            def composerChanged = prevDeps["@umark/oboe-common"] != deps["@umark/oboe-common"]
            def orgelChanged = prevDeps["@umark/orgel"] != deps["@umark/orgel"]

            def shouldBuildJava = cornetChanged || oboeChanged || orgelChanged || isManual
            def shouldBuildCli = shouldBuildJava || composerChanged || isManual
            def shouldBuildOps = cornetChanged || isManual

            if (shouldBuildCli) {
                stage("Build and push oboe-cli image") {
                    sh "docker build -t ${registry}/symphony/oboe-cli:${versionTag} $build_option Dockerfiles/cli/"
                    sh "docker push ${registry}/symphony/oboe-cli:${versionTag}"
                    sh "docker tag ${registry}/symphony/oboe-cli:${versionTag} ${registry}/symphony/oboe-cli:latest"
                    sh "docker push ${registry}/symphony/oboe-cli:latest"
                }
                stage("Build and push oracle-broker image") {
                    sh "docker build -t ${registry}/symphony/oracle-broker:${versionTag} $build_option Dockerfiles/oracle-broker/"
                    sh "docker push ${registry}/symphony/oracle-broker:${versionTag}"
                    sh "docker tag ${registry}/symphony/oracle-broker:${versionTag} ${registry}/symphony/oracle-broker:latest"
                    sh "docker push ${registry}/symphony/oracle-broker:latest"
                }
            } else {
                stage("Reuse latest version of oboe-cli image") {
                    sh "docker pull ${registry}/symphony/oboe-cli:latest"
                    sh "docker tag ${registry}/symphony/oboe-cli:latest ${registry}/symphony/oboe-cli:${versionTag}"
                    sh "docker push ${registry}/symphony/oboe-cli:${versionTag}"
                }
                stage("Reuse latest version of oracle-broker image") {
                    sh "docker pull ${registry}/symphony/oracle-broker:latest"
                    sh "docker tag ${registry}/symphony/oracle-broker:latest ${registry}/symphony/oracle-broker:${versionTag}"
                    sh "docker push ${registry}/symphony/oracle-broker:${versionTag}"
                }
            }
            if (shouldBuildJava) {
                stage("Build and push oboe-java image") {
                    sh "docker build -t ${registry}/symphony/oboe-java:${versionTag} $build_option Dockerfiles/java/"
                    sh "docker push ${registry}/symphony/oboe-java:${versionTag}"
                    sh "docker tag ${registry}/symphony/oboe-java:${versionTag} ${registry}/symphony/oboe-java:latest"
                    sh "docker push ${registry}/symphony/oboe-java:latest"
                }
            } else {
                stage("Reuse latest version of oboe-java image") {
                    sh "docker pull ${registry}/symphony/oboe-java:latest"
                    sh "docker tag ${registry}/symphony/oboe-java:latest ${registry}/symphony/oboe-java:${versionTag}"
                    sh "docker push ${registry}/symphony/oboe-java:${versionTag}"
                }
            }
            if (shouldBuildOps) {
                stage("Build and push fabric-ops image") {
                    sh "docker build -t ${registry}/hyperledger/fabric-ops:${versionTag} $build_option Dockerfiles/ops/"
                    sh "docker push ${registry}/hyperledger/fabric-ops:${versionTag}"
                    sh "docker tag ${registry}/hyperledger/fabric-ops:${versionTag} ${registry}/hyperledger/fabric-ops:latest"
                    sh "docker push ${registry}/hyperledger/fabric-ops:latest"
                }
                stage("Build and push cornet-dev image") {
                    sh "docker build -t ${registry}/symphony/cornet-dev:${versionTag} $build_option Dockerfiles/cornet-dev/"
                    sh "docker push ${registry}/symphony/cornet-dev:${versionTag}"
                    sh "docker tag ${registry}/symphony/cornet-dev:${versionTag} ${registry}/symphony/cornet-dev:latest"
                    sh "docker push ${registry}/symphony/cornet-dev:latest"
                }
            } else {
                stage("Reuse latest version of fabric-ops image") {
                    sh "docker pull ${registry}/hyperledger/fabric-ops:latest"
                    sh "docker tag ${registry}/hyperledger/fabric-ops:latest ${registry}/hyperledger/fabric-ops:${versionTag}"
                    sh "docker push ${registry}/hyperledger/fabric-ops:${versionTag}"
                }
                stage("Reuse latest version of cornet-dev image") {
                    sh "docker pull ${registry}/symphony/cornet-dev:latest"
                    sh "docker tag ${registry}/symphony/cornet-dev:latest ${registry}/symphony/cornet-dev:${versionTag}"
                    sh "docker push ${registry}/symphony/cornet-dev:${versionTag}"
                }
            }

            // This image is derived from symphony and has no dependencies 
            stage("Build and push symphony-test image") {
                sh "docker build -t ${registry}/symphony/symphony-test:${versionTag} $build_option -f Dockerfiles/symphony-test/Dockerfile ."
                sh "docker push ${registry}/symphony/symphony-test:${versionTag}"
            }

            // This image currently depends on the success of a symphony/master CircleCI deploy 
            stage("Build and push symphony-cli image") {
                sh "docker build -t ${registry}/symphony/symphony-cli:${versionTag} $build_option Dockerfiles/symphony-cli/"
                sh "docker push ${registry}/symphony/symphony-cli:${versionTag}"
                sh "docker tag ${registry}/symphony/symphony-cli:${versionTag} ${registry}/symphony/symphony-cli:latest"
                sh "docker push ${registry}/symphony/symphony-cli:latest"
            }
            
            build_changes.shouldBuildCli = shouldBuildCli
            build_changes.shouldBuildJava = shouldBuildJava
            build_changes.shouldBuildOps = shouldBuildOps
            build_changes.versionTag = versionTag
        }
        if (currentBuild.result == "NOT_BUILT") return
        if (is_release) {
            println 'release branch will be manually deployed'
            currentBuild.result = "SUCCESS"
            sendDingTalkResult()
            return
        }
        if (build_changes.shouldBuildOps) {
            set_options_fabric['fabric-ops.image.tag'] = build_changes.versionTag
            if (is_prod) {
                set_options_fabric << fabric_prod_options
            }
            deployChart name: 'fabric', ns: ns,
                        deploy_name: deploy_name_ops,
                        node_label: node_label,
                        set: set_options_fabric
        }
        if (build_changes.shouldBuildCli) {
            set_options_symphony['oboe-rest.image.tag'] = build_changes.versionTag
            set_options_symphony['oracle-broker.image.tag'] = build_changes.versionTag
        }
        if (build_changes.shouldBuildJava) {
            set_options_symphony['oboe-java.image.tag'] = build_changes.versionTag
        }
        if (build_changes.shouldBuildJava || build_changes.shouldBuildCli) {
            if (is_prod) {
                set_options_symphony << symphony_prod_options
            }
            deployChart name: 'symphony', ns: ns,
                        deploy_name: deploy_name,
                        node_label: node_label,
                        set: set_options_symphony
        }
        currentBuild.result = "SUCCESS"
        // sendDingTalkResult()
    }
    catch (Exception ex) {
        println(ex)
        currentBuild.result = "FAILED"
        // sendDingTalkResult()
    }
}  

